package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.apis.article.IArticleClient;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.constants.WmNewsMessageConstants;
import com.heima.common.exception.CustomException;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.NewsAuthDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.*;
import com.heima.utils.thread.WmThreadLocalUtils;
import com.heima.wemedia.mapper.*;
import com.heima.wemedia.service.WmNewsAutoScanService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.service.WmNewsTaskService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    @Autowired
    private WmNewsAutoScanService wmNewsAutoScanService;

    @Autowired
    private WmNewsTaskService wmNewsTaskService;

    @Autowired
    private KafkaTemplate<String,Object> kafkaTemplate;

    @Autowired
    private WmChannelMapper wmChannelMapper;

    @Autowired
    private WmUserMapper wmUserMapper;

    @Autowired
    private IArticleClient iArticleClient;


    /**
     * 获取文章列表
     * @param wmNewsPageReqDto
     * @return
     */
    @Override
    public ResponseResult findAll(WmNewsPageReqDto wmNewsPageReqDto) {

        wmNewsPageReqDto.checkParam();

        IPage<WmNews> page=new Page<>(wmNewsPageReqDto.getPage(),wmNewsPageReqDto.getSize());

        //检查参数

        //判断是否登录
        WmUser wmUser = WmThreadLocalUtils.getUser();
        if (wmUser==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        if (wmNewsPageReqDto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        LambdaQueryWrapper<WmNews> lqw=new LambdaQueryWrapper<>();
        //状态
        if (wmNewsPageReqDto.getStatus()!=null){
            lqw.eq(WmNews::getStatus,wmNewsPageReqDto.getStatus());
        }
        //频道
        if (wmNewsPageReqDto.getChannelId()!=null){
            lqw.eq(WmNews::getChannelId,wmNewsPageReqDto.getChannelId());
        }
        //时间
        if (wmNewsPageReqDto.getBeginPubDate()!=null && wmNewsPageReqDto.getEndPubDate()!=null){
            lqw.between(WmNews::getCreatedTime,wmNewsPageReqDto.getBeginPubDate(),wmNewsPageReqDto.getEndPubDate());
        }
        //关键字
        if (wmNewsPageReqDto.getKeyword()!=null){
            lqw.like(WmNews::getTitle,wmNewsPageReqDto.getKeyword());
        }
        //排序
        lqw.orderByDesc(WmNews::getCreatedTime);
        //查询自己的文章
        lqw.eq(WmNews::getUserId,wmUser.getId());

        //返回数据
        page(page, lqw);
        ResponseResult responseResult=new PageResponseResult(wmNewsPageReqDto.getPage(),wmNewsPageReqDto.getSize(),(int)page.getTotal());
        responseResult.setData(page.getRecords());

        return responseResult;
    }


    /**
     * 文章发布
     * @param wmNewsDto
     * @return
     */
    @Override
    public ResponseResult submitNews(WmNewsDto wmNewsDto) {
        //参数判断
        if (wmNewsDto==null || wmNewsDto.getContent()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //保存或修改文章
        WmNews wmNews=new WmNews();
        //属性拷贝
        BeanUtils.copyProperties(wmNewsDto,wmNews);
        //封面图片
        if (wmNewsDto.getImages()!=null && wmNewsDto.getImages().size()>0){
            //[1dddfsd.jpg,sdlfjldk.jpg]-->   1dddfsd.jpg,sdlfjldk.jpg
            //将数组变为字符串 可以将数组或集合以某拼接符拼接到一起形成新的字符串
            String imagesStr = StringUtils.join(wmNewsDto.getImages(), ",");
            wmNews.setImages(imagesStr);
        }
        //如果当前封面类型为自动 -1
        if (wmNewsDto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){
            wmNews.setType(null);
        }
        //保存或者修改
        saveOrUpdateWmNews(wmNews);
        //判断是否为草稿
        if (wmNewsDto.getStatus().equals(WmNews.Status.NORMAL.getCode())){
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        //不是草稿 保存文章内容图片与素材的关系
        //获取文章内容的图片信息
        List<String> materials= ectractUrlInfo(wmNewsDto.getContent());
        saveRelativeINfoForContent(materials,wmNews.getId());

        //不是草稿，保存文章封面图片与素材的关系，如果当前布局是自动，需要匹配封面图片
        saveRelativeInfoForCover(wmNewsDto,wmNews,materials);

        //审核文章
        //wmNewsAutoScanService.autoScanWmNews(wmNews.getId());
        //调用延迟任务
        wmNewsTaskService.addNewsToTask(wmNews.getId(),wmNews.getPublishTime());

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }




    /**
     * 第一个功能：如果当前封面类型为自动，则设置封面类型的数据
     *      * 匹配规则：
     *      * 1，如果内容图片大于等于1，小于3  单图  type 1
     *      * 2，如果内容图片大于等于3  多图  type 3
     *      * 3，如果内容没有图片，无图  type 0
     *      *
     *      * 第二个功能：保存封面图片与素材的关系
     * @param wmNewsDto
     * @param wmNews
     * @param materials
     */
    private void saveRelativeInfoForCover(WmNewsDto wmNewsDto, WmNews wmNews, List<String> materials) {
        List<String> images = wmNewsDto.getImages();

        //如果当前封面类型为自动，则设置封面类型的数据
        if(wmNewsDto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){
            //多图
            if(materials.size() >= 3){
                wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);
                images = materials.stream().limit(3).collect(Collectors.toList());
            }else if(materials.size() >= 1 && materials.size() < 3){
                //单图
                wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);
                images = materials.stream().limit(1).collect(Collectors.toList());
            }else {
                //无图
                wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);
            }

            //修改文章
            if(images != null && images.size() > 0){
                wmNews.setImages(StringUtils.join(images,","));
            }
            updateById(wmNews);
        }
        if(images != null && images.size() > 0){
            saveRelativeInfo(images,wmNews.getId(),WemediaConstants.WM_COVER_REFERENCE);
        }
    }

    /**
     * 处理文章内容图片与素材的关系
     * @param materials
     * @param newsId
     */
    private void saveRelativeINfoForContent(List<String> materials, Integer newsId) {
        saveRelativeInfo(materials,newsId,WemediaConstants.WM_CONTENT_REFERENCE);
    }

    /**
     * 保存文章图片与素材的关系到数据库中
     * @param materials
     * @param newsId
     * @param type
     */
    private void saveRelativeInfo(List<String> materials, Integer newsId, Short type) {
        if (materials!=null && !materials.isEmpty()){
            //通过素材的url查询素材的id
            List<WmMaterial> wmMaterials = wmMaterialMapper.selectList(Wrappers.
                    <WmMaterial>lambdaQuery().in(WmMaterial::getUrl, materials));
            //判断素材是否有效
            if (wmMaterials==null || wmMaterials.size()==0){
                //手动抛出异常
                throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
            }
            if (materials.size()!=wmMaterials.size()){
                throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
            }
            List<Integer> idList = wmMaterials.stream().map
                    (WmMaterial::getId).collect(Collectors.toList());
            //批量保存
            wmNewsMaterialMapper.saveRelations(idList,newsId,type);
        }
    }


    /**
     * 提取文章内容中的图片信息
     * @param content
     * @return
     */
    private List<String> ectractUrlInfo(String content) {
        List<String> materials=new ArrayList<>();
        List<Map> maps = JSON.parseArray(content, Map.class);
        for (Map map : maps) {
            if (map.get("type").equals("image")){
                String imgUrl = (String) map.get("value");
                materials.add(imgUrl);
            }
        }
        return materials;
    }


    /**
     * 保存或者修改文章
     * @param wmNews
     */
    private void saveOrUpdateWmNews(WmNews wmNews) {
        //补全属性
        wmNews.setUserId(WmThreadLocalUtils.getUser().getId());
        wmNews.setCreatedTime(new Date());
        wmNews.setSubmitedTime(new Date());
        wmNews.setEnable((short) 1);//上架
        if (wmNews.getId()==null){
            //保存
            save(wmNews);
        }else {
            //修改
            //删除文章图片和素材的关系
            wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().
                    eq(WmNewsMaterial::getNewsId,wmNews.getId()));
            updateById(wmNews);
        }
    }

    /**
     * 文章上下架
     * @param wmNewsDto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDto wmNewsDto) {
        //参数处理
        if (wmNewsDto.getId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        WmNews wmNews = getById(wmNewsDto.getId());
        if (wmNews.getArticleId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //判断文章状态
        if (!wmNews.getStatus().equals(WmNews.Status.PUBLISHED.getCode())){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"文章不是发布状态,无法上下架!");
        }
        //修改文章enable
        if (wmNewsDto.getEnable()!=null && wmNewsDto.getEnable()>-1 && wmNewsDto.getEnable()<2){
            update(Wrappers.<WmNews>lambdaUpdate().eq(WmNews::getId,wmNews.getId())
                            .set(WmNews::getEnable,wmNewsDto.getEnable()));

            if (wmNews.getArticleId()!=null){
                Map<String,Object> map=new HashMap<>();
                map.put("ArticleId",wmNews.getArticleId());
                map.put("enable",wmNewsDto.getEnable());

                kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC,JSON.toJSONString(map));

            }
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 文章手动审核 获取文章列表
     * @param newsAuthDto
     * @return
     */
    @Override
    public ResponseResult getList(NewsAuthDto newsAuthDto) {
        //参数校验
         if (newsAuthDto==null){
             return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
         }
         //分页
         Page<WmNews> wmNewsPage=new Page<>(newsAuthDto.getPage(),newsAuthDto.getSize());
         //条件查询
         LambdaQueryWrapper<WmNews> lqw=new LambdaQueryWrapper<>();
         lqw.orderByDesc(WmNews::getCreatedTime);
         //标题模糊查询
         if (StringUtils.isNotBlank(newsAuthDto.getTitle())){
             lqw.like(WmNews::getTitle,newsAuthDto.getTitle());
         }
         //状态
        if (newsAuthDto.getStatus()!=null){
            lqw.eq(WmNews::getStatus,newsAuthDto.getStatus());
        }
        page(wmNewsPage,lqw);
        PageResponseResult pageResponseResult=new PageResponseResult(
                (int)wmNewsPage.getCurrent(),(int)wmNewsPage.getSize(),(int)wmNewsPage.getTotal()
        );
        pageResponseResult.setData(wmNewsPage.getRecords());
        return pageResponseResult;
    }

    /**
     * 手动审核失败
     * @param newsAuthDto
     * @return
     */
    @Override
    public ResponseResult authFail(NewsAuthDto newsAuthDto) {
        if (newsAuthDto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        update(Wrappers.<WmNews>lambdaUpdate().set(WmNews::getStatus,2)
                .set(WmNews::getReason,newsAuthDto.getMsg()).eq(WmNews::getId,newsAuthDto.getId()));
        return ResponseResult.okResult("");
    }

    /**
     * 自媒体审核成功
     * @param newsAuthDto
     * @return
     */
    @Override
    public ResponseResult authPass(NewsAuthDto newsAuthDto) {
        if (newsAuthDto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        update(Wrappers.<WmNews>lambdaUpdate().set(WmNews::getStatus,9)
                .eq(WmNews::getId,newsAuthDto.getId()));
        //获取文章
        WmNews wmNews = getById(newsAuthDto.getId());
        ResponseResult responseResult = saveAppArticle(wmNews);
        //回填article_id
        wmNews.setArticleId((Long) responseResult.getData());
        wmNews.setStatus((short)9);
        updateById(wmNews);
        return ResponseResult.okResult("");
    }


    private ResponseResult saveAppArticle(WmNews wmNews) {
        ArticleDto articleDto=new ArticleDto();
        //属性拷贝
        BeanUtils.copyProperties(wmNews,articleDto);
        //文章布局
        articleDto.setLayout(wmNews.getType());
        //频道
        WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
        if (wmChannel!=null){
            articleDto.setChannelName(wmChannel.getName());
        }
        //作者
        articleDto.setAuthorId(wmNews.getUserId().longValue());
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        if(wmUser!=null){
            articleDto.setAuthorName(wmUser.getName());
        }
        //设置文章id
        if (wmNews.getArticleId()!=null){
            articleDto.setId(wmNews.getArticleId());
        }
        articleDto.setCreatedTime(new Date());

        ResponseResult responseResult = iArticleClient.saveArticle(articleDto);
        return responseResult;
    }
}
